package flexjson.locators;

import java.util.HashMap;
import java.util.Map;

import com.fr.base.core.util.TemplateUtils;

import flexjson.ClassLocator;
import flexjson.JSONException;
import flexjson.ObjectBinder;
import flexjson.Path;

/**
 * This implementation uses a single field out of the object as the type discriminator.
 * Each unique value of the type field is mapped to a java class using the
 * {@link TypeLocator#add(Object, Class)} method.
 */
public class TypeLocator implements ClassLocator {

    private String fieldname;
    private Map types = new HashMap();

    public TypeLocator( String fieldname ) {
        this.fieldname = fieldname;
    }

    public TypeLocator add( Object value, Class type ) {
        types.put( value, type );
        return this;
    }

    public Class locate(ObjectBinder context, Path currentPath) throws ClassNotFoundException {
        Object source = context.getSource();
        if( source instanceof Map ) {
            Map map = (Map)source;
            return (Class)types.get( map.get( fieldname ) );
        } else {
            throw new JSONException( TemplateUtils.render("${path}: Don't know how to locate types for source ${class} using fieldname ${fieldname}.  TypeLocator requires the source object be a java.util.Map in order to work.", 
            		new String[] {"path", "class", "fieldname"}, new Object[] {context.getCurrentPath(), source.getClass(), fieldname}));
        }
    }
}
